#pragma once
// -------------------------------------------------
// ZED Kit
// -------------------------------------------------
//   File Name: shell.hpp
//      Author: Ziming Li
//     Created: 2022-08-22
// -------------------------------------------------
// Copyright (C) 2022 MingYang Software Technology.
// -------------------------------------------------

#ifndef ZED_GUI_SHELL_HPP
#define ZED_GUI_SHELL_HPP

#include "../platform_sdk.h"
#include "../file/file.hpp"

#ifdef _Z_OS_WINDOWS
#   include <shellapi.h>
#   include <ShlObj.h>
#   include "../locale.hpp"
#endif

namespace zed {

class gui_shell
{
public:
    using path_t = file::path_t;

    static bool open_folder(path_t folder_path);
    static bool open_url(const char* url);
    static bool reveal_file(path_t file_path);
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifdef _Z_OS_WINDOWS
namespace detail {
bool shell_execute_open(PCWSTR pwzFile)
{
    HINSTANCE ret = ::ShellExecuteW(nullptr, L"open", pwzFile, nullptr, nullptr, SW_SHOWNORMAL);
    return reinterpret_cast<INT_PTR>(ret) > 32;
}
} // namespace detail

inline bool gui_shell::open_folder(path_t folder_path)
{
    const DWORD attr = ::GetFileAttributesW(folder_path);
    if (INVALID_FILE_ATTRIBUTES == attr || 0 == (attr & FILE_ATTRIBUTE_DIRECTORY))
        return false;
    return detail::shell_execute_open(folder_path);
}

inline bool gui_shell::open_url(const char* url)
{
    std::wstring ws = zed::multi_byte_to_wide_string(url);
    return detail::shell_execute_open(ws.c_str());
}

inline bool gui_shell::reveal_file(path_t file_path)
{
    IShellFolder *sf = nullptr;
    HRESULT hr = ::SHGetDesktopFolder(&sf);
    if (FAILED(hr))
        return false;

    bool ret = false;
    LPITEMIDLIST pidl = nullptr;
    hr = sf->ParseDisplayName(nullptr, nullptr, const_cast<PWSTR>(file_path), nullptr, &pidl, nullptr);
    if (SUCCEEDED(hr))
    {
        hr = ::SHOpenFolderAndSelectItems(pidl, 0, nullptr, 0);
        if (SUCCEEDED(hr))
            ret = true;
    }

    if (nullptr != pidl)
        ::CoTaskMemFree(pidl);
    sf->Release();
    return ret;
}
#endif // _Z_OS_WINDOWS

} // namespace zed

#endif // ZED_GUI_SHELL_HPP
